import { createElement } from 'react';
import Axios from 'axios';
// import qs from 'qs';
import { isArray, each } from 'lodash';
import { Toast } from 'antd-mobile';
import { HttpRequestCache } from 'http-request-cache';
import { IHttpUtilsProps } from '@/interface';

function generateKey(name: string, params: any) {
  return `${name}:${JSON.stringify(params)}`;
}

export default function Http(
  {
    url = '',
    method = 'GET',
    headers,
    data,
    params,
    setResult,
    setLoading,
  }: IHttpUtilsProps,
  flag: boolean = true,
  lodFlag: boolean = true,
) {
  setLoading && setLoading(true);
  let key: string;
  if (flag) {
    key = generateKey(url, { ...data, ...params });
    const _data = HttpRequestCache.get(key);
    if (_data) {
      setLoading && setLoading(false);
      setResult && setResult(_data);
      return _data;
    }
  }

  const currentHeaders = {
    'Content-type': 'application/json',
    ...headers,
  };

  const axios = Axios.create();
  axios.defaults.headers.post['Content-Type'] =
    'application/x-www-form-urlencoded;charset=UTF-8';
  axios.interceptors.request.use(config => {
    setTimeout(Toast.hide);
    lodFlag && Toast.loading('loading');
    if (method.toUpperCase() === 'POST') {
      config.headers = currentHeaders;
      // config.data = qs.stringify(data);
    }
    const token = localStorage.getItem('token');
    if (token) {
      config.headers = {
        ...config.headers,
        token,
      };
    }

    return config;
  });

  axios.interceptors.response.use(
    res => {
      setLoading && setLoading(false);
      if (res.status.toString().startsWith('2')) {
        flag && HttpRequestCache.set(key, res.data);
      } else {
        Toast.fail(res.data.msg);
      }
      setResult && setResult(res.data);
      return Promise.resolve(res.data);
    },
    err => {
      const {
        message,
        response: { status, data },
      } = err;
      if (data && data.msg) {
        let msgStr = [];
        if (isArray(data.msg)) {
          each(data.msg, item => {
            msgStr.push(createElement('div', null, item.message));
          });
        } else {
          msgStr.push(createElement('div', null, data.msg));
        }
        Toast.fail(createElement('div', null, ...msgStr));
      } else {
        Toast.fail(message);
      }
      if (data.errorCode === 10005) {
        const urlStr = encodeURIComponent(
          `${location.pathname}${location.search}`,
        );
        location.href = `/login?from=${urlStr}`;
        localStorage.clear();
      }
      const _data = {
        code: status,
        data: data,
      };
      setResult && setResult(_data);
      return Promise.resolve(_data);
    },
  );

  return axios.request({
    url: `${process.env.apiUrl}${url}`,
    method,
    data,
    params,
  });
}
